package com.microservice.base.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.microservice.base.entity.CHkRecords;
import com.microservice.base.entity.CPassThirdTrace;
import com.microservice.base.entity.TargetInfo;
import com.microservice.base.mapper.hikcommon.CHkRecordsMapper;
import com.microservice.base.mapper.smart.CPassThirdTraceMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jbx
 * @package_name com.microservice.base.task
 * @create_date 2020/12/21 13:12
 */
@Component
@Transactional
@EnableScheduling
public class syncRecords {
  @Autowired CHkRecordsMapper cHkRecordsMP;
  @Autowired CPassThirdTraceMapper cPassThirdTraceMP;
  Logger logger = LoggerFactory.getLogger(syncData.class);
  SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS+8:00");

  @Value("${schoolcode}")
  private String schoolCode;

  @Scheduled(cron = "0 0/10 * * * ?")
  public void sync() {
    // 拉取人员记录信息
    // 先查询本地数据库里是否有数据,因为数据量庞大,所以只查询第一条数据是否存在
    List<CHkRecords> cHkRecords = cHkRecordsMP.queryAllByLimit();
    if (cHkRecords.size() > 0) {
      // 当第一次无数据循环完成或者发生故障重启后进行的操作
      // startTime = 上一次的系统时间+1毫秒,endTime = 本次的系统时间,注意时间点的开闭区间
      // 因为海康时间的最小单位是毫秒,故只需要哦加上1毫秒即可
      // 海康时间的规则为: starttime<= 查询信息 <=endtime
      Map<String, Date> maxEndTime = cHkRecordsMP.getMaxEndTime();
      Date startTime = new Date(maxEndTime.get("lastSysTime").getTime() + 1);
      Date endTime = new Date();
      int pageNo = 1;
      Integer total;
      try {
        do {
          JSONObject jo = new JSONObject();
          jo.put("startTime", simpleDateFormat.format(startTime));
          jo.put("endTime", simpleDateFormat.format(endTime));
          jo.put("similarity", 80);
          jo.put("pageSize", 1000);
          jo.put("pageNo", pageNo);
          String s = HikConnection.pushHik("/api/frs/v1/event/black/search", jo.toString());
          JSONObject jsonObject = JSONObject.parseObject(s);
          JSONObject data = jsonObject.getJSONObject("data");
          total = data.getInteger("total");
          JSONArray recordslist = data.getJSONArray("list");
          for (int i = 0; i < recordslist.size(); i++) {
            List<CHkRecords> saveList = new ArrayList<>();
            JSONObject listObject = recordslist.getJSONObject(i);
            JSONObject snapInfo = listObject.getJSONObject("snapInfo");
            List<TargetInfo> targetInfoList =
                listObject.getJSONArray("targetInfoList").toJavaList(TargetInfo.class);
            tranCHKrecord(startTime, endTime, saveList, snapInfo, targetInfoList);
          }
          pageNo += 1;
        } while (total == 1000);
        logger.error("拉取records数据成功");
      } catch (Exception e) {
        logger.error("拉取records数据出错:" + e);
      }

      try {
        // 数据量很大,删除3天前的数据
        cHkRecordsMP.deleteBeforeThreeDays();
        logger.error("删除三天前数据成功....");
      } catch (Exception e) {
        logger.error("删除三天前数据失败," + e);
      }

    } else {
      // 本地数据库无数据,starttime=表中最大时间,endtime=当前系统时间
      Calendar calendar = Calendar.getInstance();
      // 设置将从2020年12月01号以来的数据全部拿到
      calendar.set(2020, 11, 01);
      Date startTime = calendar.getTime();
      Date endTime = new Date();
      int pageNo = 1;
      Integer total;
      try {
        do {
          JSONObject jo = new JSONObject();
          jo.put("startTime", simpleDateFormat.format(startTime));
          jo.put("endTime", simpleDateFormat.format(endTime));
          jo.put("similarity", 80);
          jo.put("pageSize", 1000);
          jo.put("pageNo", pageNo);
          String s = HikConnection.pushHik("/api/frs/v1/event/black/search", jo.toString());
          JSONObject jsonObject = JSONObject.parseObject(s);
          JSONObject data = jsonObject.getJSONObject("data");
          total = data.getInteger("total");
          JSONArray recordslist = data.getJSONArray("list");
          for (int i = 0; i < recordslist.size(); i++) {
            List<CHkRecords> saveList = new ArrayList<>();
            JSONObject listObject = recordslist.getJSONObject(i);
            JSONObject snapInfo = listObject.getJSONObject("snapInfo");
            List<TargetInfo> targetInfoList =
                listObject.getJSONArray("targetInfoList").toJavaList(TargetInfo.class);
            tranCHKrecord(startTime, endTime, saveList, snapInfo, targetInfoList);
          }
          pageNo += 1;
        } while (total == 1000);
        logger.error("拉取records数据成功");
      } catch (Exception e) {
        logger.error("拉取records数据出错:" + e);
      }
      // 等于1000说明后面还有数据,继续循环拿取数据
    }

    // 进行智慧管理库的同步
    // 拉取的规则,insertinto全部sync_flag=0的数据,拉取结束后,将sync_flag置为1
    List<CPassThirdTrace> cPassThirdTraceList = cHkRecordsMP.getTraceBySyncFlag(0);
    List<CHkRecords> recordsBySyncFlag = cHkRecordsMP.getBySyncFlag(0);

    List<CPassThirdTrace> addDbThirdTrace = new ArrayList<>();
    List<CHkRecords> addDbRecord = new ArrayList<>();
    for (CPassThirdTrace cPassThirdTrace : cPassThirdTraceList) {
      cPassThirdTrace.setId(UUID.randomUUID().toString().replace("-", ""));
      if ("male".equals(cPassThirdTrace.getUserSex())) {
        cPassThirdTrace.setUserSex("1");
      } else if ("female".equals(cPassThirdTrace.getUserSex())) {
        cPassThirdTrace.setUserSex("2");
      } else {
        cPassThirdTrace.setUserSex("0");
      }
      // 抓拍分类,自定义名称"TRACk"
      cPassThirdTrace.setPassType("TRACK");
      cPassThirdTrace.setDiscrenType("2");
      cPassThirdTrace.setDataSource("hikvision");
      cPassThirdTrace.setDeleted("0");
      cPassThirdTrace.setStatus("1");
      cPassThirdTrace.setUpdateTime(new Date());
      addDbThirdTrace.add(cPassThirdTrace);
    }
    for (CHkRecords updateRecord : recordsBySyncFlag) {
      updateRecord.setSyncFlag(1);
      addDbRecord.add(updateRecord);
    }
    // 进行批量插入,插入完之后更新原有数据的sync_flag
    if (addDbThirdTrace.size() > 0) {
      for (int i = 0; i <= addDbThirdTrace.size() / 500; i++) {
        cPassThirdTraceMP.saveBatch(
            addDbThirdTrace.stream().skip(i * 500).limit(500).collect(Collectors.toList()));
        cHkRecordsMP.saveBatch(
            addDbRecord.stream().skip(i * 500).limit(500).collect(Collectors.toList()));
      }
      logger.error("同步到云端行为轨迹成功!");
    }
  }

  public void tranCHKrecord(
      Date startTime,
      Date endTime,
      List<CHkRecords> saveList,
      JSONObject snapInfo,
      List<TargetInfo> targetInfoList)
      throws ParseException {
    CHkRecords saveRecord = new CHkRecords();
    saveRecord.setId(UUID.randomUUID().toString().replace("-", ""));
    saveRecord.setSyncFlag(0);
    saveRecord.setStarttime(startTime);
    saveRecord.setEndtime(endTime);
    saveRecord.setBgkUrl((String) snapInfo.get("bkgUrl"));
    saveRecord.setSnapUrl((String) snapInfo.get("snapUrl"));
    saveRecord.setCameraindexCode((String) snapInfo.get("cameraIndexcode"));
    saveRecord.setCameraName((String) snapInfo.get("cameraName"));
    saveRecord.setEventtime(hikDate(snapInfo.get("eventTime").toString()));
    for (TargetInfo targetInfo : targetInfoList) {
      saveRecord.setName(targetInfo.getName());
      saveRecord.setSex(targetInfo.getSex());
      saveRecord.setSimilarity(targetInfo.getSimilarity());
      saveRecord.setCertificateType(targetInfo.getCertificateType());
      saveRecord.setCertificateNumber(targetInfo.getCertificateNumber());
      saveRecord.setFaceUrl(targetInfo.getFaceUrl());
      saveRecord.setFaceinfoindexCode(targetInfo.getFaceInfoIndexcode());
      saveList.add(saveRecord);
    }
    cHkRecordsMP.saveBatch(saveList);
    logger.error("存入records成功,数据有:" + saveList);
  }

  public Date hikDate(String date) throws ParseException {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String replace = date.substring(0, 18).replace("T", " ");
    Date parse = simpleDateFormat.parse(replace);
    return parse;
  }
}
